#include "LayerOptionsWrapper.h"

#include <pybind11/operators.h>
#include <pybind11/stl.h>

#include <odv/odvCore/LayerOptions.h>

namespace py = pybind11;
using namespace odv;

// 枚举绑定实现
void bind_LayerType(py::module_ &m) {
  py::enum_<LayerType>(m, "LayerType")
      .value("None", LayerType::None)
      .value("ColorMap", LayerType::ColorMap)
      .value("Image", LayerType::Image)
      .value("ContourLine", LayerType::ContourLine)
      .value("PointIcon", LayerType::PointIcon)
      .value("Feature", LayerType::Feature)
      .value("ValuePlots", LayerType::ValuePlots)
      .value("Graticule", LayerType::Graticule)
      .export_values();
}

void bind_DataDimensionOrder(py::module_ &m) {
  py::enum_<DataDimensionOrder>(m, "DataDimensionOrder")
      .value("LatLong", DataDimensionOrder::LatLong)
      .value("DepthLatLong", DataDimensionOrder::DepthLatLong)
      .value("TimeLatLong", DataDimensionOrder::TimeLatLong)
      .value("TimeDepthLatLong", DataDimensionOrder::TimeDepthLatLong)
      .export_values();
}

void bind_RenderMode(py::module_ &m) {
  py::enum_<RenderMode>(m, "RenderMode")
      .value("Solid", RenderMode::Solid)
      .value("Mesh", RenderMode::Mesh)
      .value("Point", RenderMode::Point)
      .export_values();
}

void bind_ShadingMode(py::module_ &m) {
  py::enum_<ShadingMode>(m, "ShadingMode")
      .value("Flat", ShadingMode::Flat)
      .value("Smooth", ShadingMode::Smooth)
      .export_values();
}

void bind_PointIconType(py::module_ &m) {
  py::enum_<PointIconOptions::PointIconType>(m, "PointIconType")
      .value("Arrow", PointIconOptions::PointIconType::Arrow)
      .value("WindBarbs", PointIconOptions::PointIconType::WindBarbs)
      .value("Image", PointIconOptions::PointIconType::Image)
      .value("Count", PointIconOptions::PointIconType::Count)
      .export_values();
}

void bind_PointIconDataType(py::module_ &m) {
  py::enum_<PointIconOptions::DataType>(m, "PointIconDataType")
      .value("UV", PointIconOptions::DataType::UV)
      .value("Direction", PointIconOptions::DataType::Direction)
      .value("DirectionMagnitude",
             PointIconOptions::DataType::DirectionMagnitude)
      .export_values();
}

void bind_ImageDriver(py::module_ &m) {
  py::enum_<ImageOptions::Driver>(m, "ImageDriver")
      .value("GDAL", ImageOptions::Driver::GDAL)
      .value("TMS", ImageOptions::Driver::TMS)
      .value("OSG", ImageOptions::Driver::OSG)
      .value("Custom", ImageOptions::Driver::Custom)
      .export_values();
}

// 模板类绑定实现
void bind_DataRangeTemplate(py::module_ &m) {
  py::class_<DataRangeTemplate<float>>(m, "DataRange")
      .def(py::init<float, float>(), py::arg("start") = 0.0f,
           py::arg("span") = 0.0f)
      .def("set", &DataRangeTemplate<float>::set)
      .def_readwrite("start", &DataRangeTemplate<float>::start)
      .def_readwrite("span", &DataRangeTemplate<float>::span);
}

// 基类绑定实现
void bind_LayerOptions(py::module_ &m) {
  py::class_<LayerOptions, std::shared_ptr<LayerOptions>>(m, "LayerOptions")
      .def(py::init<>())
      .def(py::init<const LayerOptions &>())
      .def("getLayerType", &LayerOptions::getLayerType)
      .def_readwrite("name", &LayerOptions::name)
      .def_readwrite("urls", &LayerOptions::urls)
      .def_readwrite("varNames", &LayerOptions::varNames)
      .def_readwrite("units", &LayerOptions::units)
      .def_readwrite("dimOrder", &LayerOptions::dimOrder)
      .def_readwrite("timeRange", &LayerOptions::timeRange)
      .def_readwrite("depthRange", &LayerOptions::depthRange)
      .def_readwrite("latRange", &LayerOptions::latRange)
      .def_readwrite("longRange", &LayerOptions::longRange)
      .def_readwrite("colorBarOptions", &LayerOptions::colorBarOptions)
      .def_readwrite("clipDisplayedRangeMinValue",
                     &LayerOptions::clipDisplayedRangeMinValue)
      .def_readwrite("clipDisplayedRangeMaxValue",
                     &LayerOptions::clipDisplayedRangeMaxValue)
      .def_readwrite("invalidValue", &LayerOptions::invalidValue);
}

// 派生类绑定实现
void bind_ColorMapOptions(py::module_ &m) {
  py::class_<ColorMapOptions, LayerOptions, std::shared_ptr<ColorMapOptions>>(
      m, "ColorMapOptions")
      .def(py::init<>())
      .def_readwrite("edgeFeather", &ColorMapOptions::edgeFeather)
      .def_readwrite("shadingMode", &ColorMapOptions::shadingMode)
      .def_readwrite("stacks", &ColorMapOptions::stacks)
      .def_readwrite("slices", &ColorMapOptions::slices)
      .def_readwrite("enableMask", &ColorMapOptions::enableMask)
      .def_readwrite("maskUrl", &ColorMapOptions::maskUrl)
      .def_readwrite("maskVarName", &ColorMapOptions::maskVarName)
      .def_readwrite("maskDimOrder", &ColorMapOptions::maskDimOrder)
      .def_readwrite("maskSampleSteps", &ColorMapOptions::maskSampleSteps)
      .def_readwrite("extrapolationRadius",
                     &ColorMapOptions::extrapolationRadius);
}

void bind_ImageOptions(py::module_ &m) {
  py::class_<ImageOptions, LayerOptions, std::shared_ptr<ImageOptions>>(
      m, "ImageOptions")
      .def(py::init<>())
      .def_readwrite("driver", &ImageOptions::driver)
      .def_readwrite("opacity", &ImageOptions::opacity)
      .def_readwrite("color", &ImageOptions::color)
      .def_readwrite("imageLatOrigin", &ImageOptions::imageLatOrigin)
      .def_readwrite("imageLatSpan", &ImageOptions::imageLatSpan)
      .def_readwrite("imageLonOrigin", &ImageOptions::imageLonOrigin)
      .def_readwrite("imageLonSpan", &ImageOptions::imageLonSpan);
}

void bind_ContourLineOptions(py::module_ &m) {
  py::class_<ContourLineOptions, LayerOptions,
             std::shared_ptr<ContourLineOptions>>(m, "ContourLineOptions")
      .def(py::init<>())
      .def_readwrite("contourBase", &ContourLineOptions::contourBase)
      .def_readwrite("contourInterval", &ContourLineOptions::contourInterval)
      .def_readwrite("contourEnd", &ContourLineOptions::contourEnd)
      .def_readwrite("lineWidth", &ContourLineOptions::lineWidth)
      .def_readwrite("showContourLabel", &ContourLineOptions::showContourLabel)
      .def_readwrite("labelCharacterSize",
                     &ContourLineOptions::labelCharacterSize)
      .def_readwrite("labelFont", &ContourLineOptions::labelFont)
      .def_readwrite("labelTextColor", &ContourLineOptions::labelTextColor)
      .def_readwrite("cullSmallLines", &ContourLineOptions::cullSmallLines)
      .def_readwrite("smallLinePointCountThreshold",
                     &ContourLineOptions::smallLinePointCountThreshold);
}

void bind_PointIconOptions(py::module_ &m) {
  py::class_<PointIconOptions, LayerOptions, std::shared_ptr<PointIconOptions>>(
      m, "PointIconOptions")
      .def(py::init<>())
      .def_readwrite("type", &PointIconOptions::type)
      .def_readwrite("dataType", &PointIconOptions::dataType)
      .def_readwrite("enalbeLengthScalability",
                     &PointIconOptions::enalbeLengthScalability)
      .def_readwrite("arrowBaseLength", &PointIconOptions::arrowBaseLength)
      .def_readwrite("arrowAspectRatio", &PointIconOptions::arrowAspectRatio)
      .def_readwrite("arrowLineWidth", &PointIconOptions::arrowLineWidth)
      .def_readwrite("samplingStep", &PointIconOptions::samplingStep)
      .def_readwrite("enableColorBar", &PointIconOptions::enableColorBar)
      .def_readwrite("baseColor", &PointIconOptions::baseColor);
}

void bind_FeatureOptions(py::module_ &m) {
  py::class_<FeatureOptions, LayerOptions, std::shared_ptr<FeatureOptions>>(
      m, "FeatureOptions")
      .def(py::init<bool, bool, bool, bool>(), py::arg("isDrawLine") = true,
           py::arg("isDrawPolygon") = true, py::arg("isDrawPoint") = false,
           py::arg("isDrawText") = false)
      .def_readwrite("fontContent", &FeatureOptions::fontContent)
      .def_readwrite("fontName", &FeatureOptions::fontName)
      .def_readwrite("fontSize", &FeatureOptions::fontSize)
      .def_readwrite("fontColor", &FeatureOptions::fontColor)
      .def_readwrite("pointColor", &FeatureOptions::pointColor)
      .def_readwrite("pointSize", &FeatureOptions::pointSize)
      .def_readwrite("lineWidth", &FeatureOptions::lineWidth)
      .def_readwrite("lineColor", &FeatureOptions::lineColor)
      .def_readwrite("fillColor", &FeatureOptions::fillColor)
      .def("getEnableTextDrawing", &FeatureOptions::getEnableTextDrawing)
      .def("getEnablePointDrawing", &FeatureOptions::getEnablePointDrawing)
      .def("getEnableLineDrawing", &FeatureOptions::getEnableLineDrawing)
      .def("getEnablePolygonDrawing", &FeatureOptions::getEnablePolygonDrawing);
}

void bind_ValuePlotsOptions(py::module_ &m) {
  py::class_<ValuePlotsOptions, LayerOptions,
             std::shared_ptr<ValuePlotsOptions>>(m, "ValuePlotsOptions")
      .def(py::init<>())
      .def_readwrite("autoSampling", &ValuePlotsOptions::autoSampling)
      .def_readwrite("autoSamplingMaxRows",
                     &ValuePlotsOptions::autoSamplingMaxRows)
      .def_readwrite("samplingStep", &ValuePlotsOptions::samplingStep)
      .def_readwrite("textFont", &ValuePlotsOptions::textFont)
      .def_readwrite("textColor", &ValuePlotsOptions::textColor)
      .def_readwrite("characterSize", &ValuePlotsOptions::characterSize);
}

void bind_GraticuleOptions(py::module_ &m) {
  py::class_<GraticuleOptions, LayerOptions, std::shared_ptr<GraticuleOptions>>(
      m, "GraticuleOptions")
      .def(py::init<>())
      .def_readwrite("lineCount", &GraticuleOptions::lineCount)
      .def_readwrite("resolutions", &GraticuleOptions::resolutions)
      .def_readwrite("lineVisible", &GraticuleOptions::lineVisible)
      .def_readwrite("latLabelVisible", &GraticuleOptions::latLabelVisible)
      .def_readwrite("lonLabelVisible", &GraticuleOptions::lonLabelVisible)
      .def_readwrite("lineColor", &GraticuleOptions::lineColor)
      .def_readwrite("labelColor", &GraticuleOptions::labelColor)
      .def_readwrite("labelHaloColor", &GraticuleOptions::labelHaloColor)
      .def_readwrite("lineWidth", &GraticuleOptions::lineWidth);
}